from xml.sax import make_parser
from xml.sax.handler import ContentHandler
import sys
import getopt
import os



class ClassGenerator(ContentHandler):
    """ Handler for the xml files. It builds the class as it parses the xml. Once parsed, the renderClass() function will output the pretty formatted text. """
    
    def __init__(self):
        self.strUiElements = ''
        self.strImports = ''
        self.strClassName = 'TwitterUi'
        self.strPackageName  = 'com.mukto.whatsup'
        self.lines = []
        self.imports = []
        self.members = []
        self.indentLevel = 0
        self.xmlFile = 'twitter'
        self.outputDirectory = '.'
        self.strOutput = []

        self.generateImports()

    # private functions
    
    def _increaseIndentLevel(self):
        self.indentLevel += 1

    def _decreaseIndentLevel(self):
        if self.indentLevel > 0 :
            self.indentLevel -= 1

    def _printLine(self, line):
        self.strOutput.append('\t' * self.indentLevel +  line)
        
    def generateImports(self):
        """Include all universal imports"""
        self.imports.append('import android.content.Context;')
        self.imports.append('import android.util.AttributeSet;')
        self.imports.append('import android.view.LayoutInflater;')
        self.imports.append('import android.view.View;')

    def addNativeUiElement(self, className, elementId):
        """Adding a native widget to the class (eg. TextView, ImageView, etc) """
        
        offset = len('@+id/')
        elementName = elementId[offset:]
        toret = 'this.%s = (%s) view.findViewById(R.id.%s);' % (elementName, className, elementName)
        toimport = 'import android.widget.%s;' % (className)
        member = 'public %s %s;' % (className, elementName)

        self.imports.append(toimport)
        self.lines.append(toret)
        self.members.append(member)
        return toret

    def setClassName(self, className):
        self.strClassName = className

    def setPackageName(self, packageName):
        self.strPackageName = packageName

    def setXmlFile(self, xmlfile):
        self.xmlFile = xmlfile
    
    def setOutputDirectory(self, outputDir):
        self.outputDirectory = outputDir
    
    def renderClass(self):
        if self.strPackageName != '':
            self._printLine('package %s.ui;' % (self.strPackageName))
            self._printLine('import %s.R;' % (self.strPackageName))

        for l in self.imports:
            self._printLine(l)

        self._printLine('\n')
        
        if self.strClassName == '':
            self.strClassName = 'Ui'
            
        self._printLine('public class %s extends LinearLayout {' % (self.strClassName))
        self._increaseIndentLevel()
        for l in self.members:
            self._printLine(l)

        self._printLine('\n')
        self._printLine('private void inflateLayout(Context context) {')
        self._increaseIndentLevel()
        self._printLine('LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);')
        self._printLine('View view = layoutInflater.inflate(R.layout.%s, this);' % (self.xmlFile))
        self._printLine('')
        for code in self.lines:
            self._printLine(code)    
        self._decreaseIndentLevel()
        self._printLine('')
        self._printLine('}')
        
        self._printLine('public %s(Context context, AttributeSet attrs) {' % (self.strClassName))
    	self._increaseIndentLevel()
    	self._printLine('super(context, attrs);')
    	self._printLine('inflateLayout(context);')
    	self._decreaseIndentLevel();
        self._printLine('}')
    	self._printLine('')
    	
    	self._printLine('public %s(Context context) {' % (self.strClassName));
    	self._increaseIndentLevel()
    	self._printLine('super(context);')
    	self._printLine('inflateLayout(context);')
    	self._decreaseIndentLevel();
    	self._printLine('}')
    	self._printLine('')
    
        self._decreaseIndentLevel()
        self._printLine('')
        self._printLine('}')
        
        return '\n'.join(self.strOutput)

    def startElement(self, name, attr):
        if len(attr) > 0 and 'android:id' in attr:
            id = attr['android:id']
            self.addNativeUiElement(name, id)
            
            
    def endElement(self, name):
        pass

    def characters(self, content):
        pass

def main():
    files = []
    
    #handle command line arguments 
    packageName = ''
    outputDir = ''
    opts, args = getopt.getopt(sys.argv[1:], "p:o:")
    for t in opts:
        if '-p' in t:
            packageName = t[1]
        if '-o' in t:
            outputDir = t[1]
    
    for arg in args:
        files.append(arg)

    if len(files) == 0:
        print 'No files to process, please enter file names as command-line parameters'
        exit(0)

    for afile in files:
        layoutFileName = afile.split('/')[-1][:-4]
        className = ''.join([x.title() for x in layoutFileName.split('_')]) + 'Ui'
        
        
        generator = ClassGenerator()
        generator.setXmlFile(layoutFileName)
        generator.setClassName(className)
        generator.setPackageName(packageName)
        
        if outputDir == '':
            if not os.path.exists("./Ui"):
                os.makedirs("Ui")
            outputDir = './Ui'
        generator.setOutputDirectory(outputDir)
        
        parser = make_parser()                      
        parser.setContentHandler(generator)
        parser.parse(afile)
        
        output = generator.renderClass()
        
        outputFileName = ''        
        outputFileName = outputDir + "/" + className + '.java'
        print outputFileName
        
        outputFile = open(outputFileName, 'w')
        
        outputFile.write(output)
        outputFile.close()
        


if __name__ == '__main__':
    main()


